package com.qf.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qf.blog.commons.utils.EmailUtils;
import com.qf.blog.commons.utils.UUIDUtils;
import com.qf.blog.dto.EmailDto;
import com.qf.blog.dto.TokenDto;
import com.qf.blog.entity.User;
import com.qf.blog.handler.BlogException;
import com.qf.blog.mapper.UserMapper;
import com.qf.blog.service.UserService;
import com.qf.blog.service.UserTokenService;
import com.qf.blog.vo.UserVo;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * User: key
 * ClassName:UserServiceImpl
 * Date: 2023/6/2
 * Time: 20:10
 * description:
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private EmailUtils emailUtils;

    @Autowired
    private UserTokenService userTokenService;

    /**
     * 注册
     */
    @Override
    public void register(UserVo userVo) {

        // 1.先判断这个邮箱是否已经被注册了
        User dbUser = getUserByEmail(userVo.getEmail());
        if (dbUser != null) {
            throw new BlogException(1001, "邮箱已被注册");
        }

        // 判断用户名是否被注册
        dbUser = getUserByUsername(userVo.getUsername());
        if (dbUser != null) {
            throw new BlogException(1001, "用户名已经被注册");
        }

        // 2.密码加密
        User user = new User();
        user.setUsername(userVo.getUsername());
        user.setPassword(BCrypt.hashpw(userVo.getPwd(),BCrypt.gensalt()));
        user.setEmail(userVo.getEmail());
        user.setStatus(0); // 未激活
        user.setActivationCode(UUIDUtils.getId()); // 设置激活码?激活的时候使用
        user.setCreateTime(new Date()); // 当前时间

        // 3.新用户入库
        int insert = baseMapper.insert(user);

        // 4.给用户的邮箱发送激活连接
        if (insert > 0) {
            String url = "http://www.blog.com:8080/blog/user/activation?code=" + user.getActivationCode(); // 因为这个连接在邮箱中点击的，所以不要写localhost
            EmailDto email = new EmailDto();
            email.setTo("1479697956@qq.com");
            email.setTitle("博客账号激活邮件");
            email.setContent("恭喜您注册成功，为了检测您是否为机器人，请激活后使用，点击<a href = '" + url + "'>这里</a>激活");
            email.setCc("1479697956@qq.com");
            // 发送邮件这个方法耗时最长，使用启动一个线程异步来调用
            new Thread(() -> {
                emailUtils.sendEmail(email);
            }).start();
            /*1913432492@qq.com*/
        }
    }

    @Override
    public User getUserByEmail(String email) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email);
        return userMapper.selectOne(queryWrapper);
    }

    @Override
    public Integer updateUserStatus(String code) {
        return userMapper.updateUserStatus(code);
    }

    @Override
    public User getUserByUsername(String username) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        return userMapper.selectOne(queryWrapper);
    }

    @Override
    public Integer updateUserHeader(Integer id, String fileUrl) {
        return userMapper.updateUserHeader(id,fileUrl);
    }

    @Override
    public TokenDto login(String username, String password) {
        // 1.根据用户名查询是否存在
        User user = getUserByUsername(username);

        if (user == null) {
            throw new BlogException();
        }

        // 2.密码的比对
        //加密（参数1：待加密的密码，参数2：调用获取盐值的方法）
        String dbPw = BCrypt.hashpw(password,BCrypt.gensalt());
        //判断密码是否相同
        //如果不同则报错
        if (!BCrypt.checkpw(password, dbPw)) {
            throw new BlogException(1001, "用户名或密码错误");
        }

        // 3.账号是否激活
        if (user.getStatus() == 0) {
            throw new BlogException(1002, "账号未激活");
        }

        // 4.创建一个userToken
        TokenDto userToken = userTokenService.create(user);

        // 5.返回userTOken给Controller
        return userToken;
    }

    @Override
    public void updateByEmail(String email, String body) {
        userMapper.updateByEmail(email,body);
    }

    @Override
    public boolean updeteUser(String email, String emailVerifyCode) {
        return userMapper.updete(email,emailVerifyCode);
    }
}
